﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Game.ui;
using GameFramework.common;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UIElements;

namespace GameFramework.UI
{
    public class SceneViewManager:MonoBehaviour
    {
        
        //场景视图管理器的名字
        [FormerlySerializedAs("name")] [HideInInspector]
        public string managerName;
        
        [SerializeField]
        private UIDocument _uiDocument;
        
        //当前激活的View
        private BaseView currentView;
        
        public VisualElement RootElement
        {
            get
            {
                return _uiDocument.rootVisualElement;
            }
        }
        
        //view类型和view实例的映射
        private Dictionary<Type, BaseView> _views = new Dictionary<Type, BaseView>();
        //view实例和presenter实例的映射
        private Dictionary<BaseView, object> view2Presenter = new Dictionary<BaseView, object>();

        //view栈
        private Stack<BaseView> _viewStack = new Stack<BaseView>();

        private void Start()
        {
            // _uiDocument.rootVisualElement = RootElement;
            NullRefChecker.Validate(this);
            //加载所有UI，所有场景的UI，包括主场景UI，战斗场景UI，等
            //切换到默认显示的UI。其他UI对象隐藏
            initName();

            preLoadViews();
            //预缓存所有的View视图
        }

        private void initName()
        {
            managerName = gameObject.name;
            if (managerName.EndsWith("UI"))
            {
                managerName = managerName.Substring(0,managerName.Length - 2)
;            }

            Debug.Log("ui场景名："+managerName);
        }

        public void recoverViewStack()
        {
            if (_viewStack.Count == 0)
            {
                return;
            }

            BaseView[] baseViews = _viewStack.ToArray();
            foreach (BaseView baseView in baseViews)
            {
                baseView.ShowImmediately();
            }
        }



        public void preLoadViews()
        {
            if (!UIManager.baseViewTypeGroupBySceneName.ContainsKey(managerName))
            {
                return;
            }
            List<Type> array = UIManager.baseViewTypeGroupBySceneName[managerName];
            foreach (var type in array)
            {
                BaseView baseView = getView(type);
                if (baseView == null)
                {
                    Debug.LogError("创建view实例失败："+type.FullName);;
                    continue;
                }
            }

            hideAllViewImmediately();
        }
        
        public void hideAllViewImmediately()
        {
            foreach (BaseView view in _views.Values)
            {
                
                view.HideImmediately();
            }
        }
        public void show<T>(bool add2Stack = true)
        {
            BaseView view = getView(typeof(T));
            if (view == null)
            {
                Debug.LogError("view视图不存在："+typeof(T).Name);
                return; 
            }
            

            if (view == currentView)
            {
                return;
            }
            //待显示的view已经在队列了,且不是最后一个，移除待显示view后面的
            if (_viewStack.Contains(view))
            {
                while (_viewStack.Peek()!=view)
                {
                    BaseView baseView = _viewStack.Pop();
                    baseView.hide();
                }
                _viewStack.Peek().show();
                currentView = _viewStack.Peek();
                return;
            }
            //新的视图加到队列中
            if (currentView != null)
            {
                if (!_viewStack.Contains(currentView))
                {
                    currentView.hide();
                }
                else
                {
                    currentView.pause();
                }

            }
            
            if (add2Stack)
            {
                _viewStack.Push(view);
            }
            currentView = view;
            view.show();
        }
        
        /**
 * 关闭最上层界面
 */
        public void hide<T>()
        {
            Type baseViewType = typeof(T);
            if (!_views.ContainsKey(baseViewType))
            {
                return;
            }
            //TODO 如果待隐藏的界面是队列中间的视图，则把待隐藏界面以及队列后面的界面都隐藏
            BaseView view = _views[baseViewType];
            
            if (!_viewStack.Contains(view) && currentView==view)
            {
                view.hide();
                currentView = null;
                return;
            }

            while (_viewStack.Peek()!=view)
            {
                BaseView hideView = _viewStack.Pop();
                hideView.hide();
            }
            //TODO 最后一个界面无法关闭?有的场景运行关闭所有界面，比如拍照的时候
            //但是最后一个界面能关闭的话，一般有快捷键恢复
            if (_viewStack.Count == 1)
            {
                return;
            }

            view.hide();
            _viewStack.Pop();
            //TODO 上一个面板
            if (_viewStack.Count > 0)
            {
                BaseView lastView = _viewStack.Peek();
                if (lastView != null)
                {
                    lastView.reUse();
                }
            }
        }
        public BaseView getView(Type viewType)
        {
            if (!typeof(BaseView).IsAssignableFrom(viewType))
            {
                throw new Exception("无法获取非BaseView类型的view实例");
            }

            if (!_views.ContainsKey(viewType))//TODO 如果显示的不是同一个document下的节点呢？
            {

                VisualElement visualElement = RootElement.Q<VisualElement>(viewType.Name);
                if (visualElement == null)
                {
                    Debug.LogError("根Element中未找到view对应的元素:"+viewType.Name);
                    return null;
                }

                PresenterAttribute presenterAttribute = viewType.GetCustomAttribute<PresenterAttribute>();
                object presenter = null;
                if (presenterAttribute == null)
                {
                    Debug.LogWarning($"{viewType.Name} 未添加PresenterAttribute，无法关联对应的Presenter");
                }
                else
                {
                    Type presenterType = presenterAttribute.type;
                    if (presenterType == null)
                    {
                        Debug.LogWarning($"{viewType.Name} 中PresenterAttribute未配置persenter类型，无法关联对应的Presenter");
                    }
                    else
                    {
                        presenter = presenterType.Assembly.CreateInstance(presenterType.FullName);
                    }
                }

                //创建关联的view类
                BaseView instance = viewType.Assembly.CreateInstance(viewType.FullName) as BaseView;
                instance.setRootElement(visualElement);
                ViewAttribute viewAttribute = viewType.GetCustomAttribute<ViewAttribute>();
                instance.sceneViewManagerName = viewAttribute.SceneViewManagerName;
                _views.Add(viewType,instance);
                if (presenter != null)
                {
                    view2Presenter.Add(instance,presenter);
                }

                return instance ;
            }

            return _views[viewType];
        }

        public void back()
        {
            if (_viewStack.Count < 2)
            {
                Debug.LogWarning("没有上一个界面了！");
                return;
            }

            BaseView view = _viewStack.Peek();
            
            view.hide();
            _viewStack.Pop();
            //显示上一个面板
            BaseView lastView = _viewStack.Peek();
            lastView.reUse();
        }
    }
}